#ifndef CPU_H
#define CPU_H

#include "comm/types.h"




// 定义初始化tss结构的efalgs，不可以关中断好吧
#define EFLAGS_DEFAULT (1<<1)
// 保持开中断
#define EFLAGS_IF (1 << 9)


// define the gdt attribute bits
#define SEG_G (1 << 15)        //段限制长的颗粒度，1为4k单位
#define SEG_D (1 << 14)        // setting 1, 兼容
#define SEG_P_PRESENT (1 << 7) // 有效位
#define SEG_DPL0 (0 << 5)      // 特权级0，最高特权级
#define SEG_DPL3 (3 << 5)      // 特权级3，最低权限
#define SEG_S_SYSTEM (0 << 4) // 是否是系统段，如调用门或者中断
#define SEG_S_NORMAL (1 << 4) // 0system segment or 1code segment or data segment
#define SEG_TYPE_CODE (1 << 3) // 指定其为代码段
#define SEG_TYPE_DATA (0 << 3) // 数据段
#define SEG_TYPR_TSS (9 << 0) // 32位TSS

#define SEG_TYPE_RW (1 << 1) // 是否可写可读，不设置为只读
#define SEG_TYPE_E (0 << 1) // segment only can execute,not write

#define SEG_CPL0 (0 << 0)
#define SEG_CPL3 (3 << 0)

#define SEG_RPL0 (0 << 0)
#define SEG_RPL3 (3 << 0)
/**
 * tss描述符
 */
typedef struct _tss_t
{
    uint32_t pre_link;
    uint32_t esp0,ss0,esp1,ss1,esp2,ss2;
    uint32_t cr3;
    uint32_t eip,eflags,eax,ecx,edx,ebx,esp,ebp,esi,edi;
    uint32_t es,cs,ss,ds,fs,gs;
    uint32_t ldt;
    uint32_t io_map; 
    // uint32_t ssp;
}tss_t;

// pragma 指令强制编译器按此流程进行编译操作，对于内存地址严格按此格式于顺序排列，这也对照了gdt表的结构
#pragma pack(1)
// define gdt struct
/**
 * GDT描述符
 */
typedef struct _segment_desc_t
{
    uint16_t limit15_0;
    uint16_t base15_0;
    uint8_t base23_16;
    uint16_t attr;
    uint8_t base31_24;
} segment_desc_t;
#pragma pack()

// declare the funcion
void cpu_init(void);
void init_gdt(void);
void segment_desc_set(int selector, uint32_t base, uint32_t limit, uint16_t attr);
int gdt_alloc_desc(void);

void gdt_free_sel(int sel);

#endif